const { Transform } = require('stream');
const soap = require('soap');
const _ = require('lodash');
const moment = require('moment');
const utils = require('../../utils');

const soapApi = {
  client: undefined,
  async run(method, args, returnResult = false) {
    return new Promise((resolve, reject) => {
      this.client[method](args, (err, result) => {
        if (err) {
          return reject(err)
        } else {
          if (!result) {
            reject('返回值为空')
          }
          if (returnResult) {
            return resolve(result)
          }
          try {
            let data = result[method + 'Result']
            resolve(data)
          } catch (e) {
            resolve('')
          }
        }
      })
    })
  },
  async connect(url, auth = '', options = {}) {
    if (this.client) return this.client
    return new Promise((resolve, reject) => {
      soap.createClient(url, options, (err, client) => {
        if (err) {
          return reject(err)
        }
        client.addSoapHeader(auth);
        this.client = client
        resolve(client)
      })
    })
  }
};

module.exports = async function ({ url, method, inFormat, outFormat } = {}) {
  const stream = new Transform({ objectMode: true });
  inFormat = utils.parseFunction(inFormat);
  outFormat = utils.parseFunction(outFormat);
  await soapApi.connect(url);

  stream._transform = async function (chunk, encoding, callback) {
    utils.debug('soapTransform [chunk]:', chunk);
    const params = inFormat ? await inFormat(chunk, { _, moment, utils }) : chunk;
    const r = await soap.run(method, params);
    const obj = outFormat ? await outFormat(r, { _, moment, utils, $$: chunk }) : r;
    stream.push(obj);
    callback();
  };

  stream.on('finish', function () {
    utils.debug('soapTransform [finish]');
  });

  return stream;
};